from typing import Protocol, List, Callable
from dataclasses import dataclass
from datetime import datetime
import abc
import pandas as pd


class Position(Protocol):
    ...


class Account(Protocol):

    def get_position(self, symbol: str, side: int) -> List[Position]:
        ...


class Context(Protocol):
    now: datetime
    mode: int

    @abc.abstractmethod
    def subscribe(self,
                  symbols: str,
                  frequency='1d',
                  count: int = 1,
                  wait_group: bool = False,
                  wait_group_timeout: str = '10s',
                  unsubscribe_previous: bool = False):
        ...

    @abc.abstractmethod
    def get_data(self, symbol: str, freq: str, count: int, fields: str) -> pd.DataFrame:
        ...

    @abc.abstractmethod
    def get_account(self) -> Account:
        ...

    @abc.abstractmethod
    def order_volume(self,
                     symbol: str,
                     volume: int,
                     side: int,
                     position_effect: int,
                     order_type: int):
        ...

    @abc.abstractmethod
    def schedule(self, schedule_func: Callable[['Context'], ...], date_rule: str, time_rule: str):
        raise NotImplementedError

    @abc.abstractmethod
    def history_n(self,
                  symbol: str,
                  frequency: str,
                  end_time: datetime,
                  fields: str,
                  count: int) -> pd.DataFrame:
        ...

    @abc.abstractmethod
    def current(self, symbol: str) -> pd.DataFrame:
        ...


class Bar(Protocol):
    open: float
    high: float
    low: float
    close: float


@dataclass
class Order(dict):
    status: int
    side: int
    position_effect: int


class Strategy(Protocol):

    def log(self, *args: str) -> None:
        print(*args)

    def on_init(self, context: Context):
        pass

    def on_bar(self, context: Context, bars: List[Bar]):
        pass


